package com.kxmall.framework.interceptor;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.stp.StpUtil;
import com.kxmall.common.core.domain.model.LoginUser;
import com.kxmall.common.helper.LoginHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 用户信息一致性检查拦截器
 * 检查ThreadLocal和Token中的用户信息是否一致，防止串号
 *
 * @author kxmall
 */
@Slf4j
@Component
public class UserConsistencyInterceptor implements HandlerInterceptor {

    private static final String LOGIN_USER_KEY = "loginUser";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        
        // 只对已登录用户进行检查
        if (!StpUtil.isLogin()) {
            return true;
        }

        try {
            // 获取ThreadLocal中的用户信息
            LoginUser threadLocalUser = (LoginUser) SaHolder.getStorage().get(LOGIN_USER_KEY);
            
            // 获取Token中的用户信息
            LoginUser tokenUser = (LoginUser) StpUtil.getTokenSession().get(LOGIN_USER_KEY);
            
            // 如果两者都存在，检查一致性
            if (threadLocalUser != null && tokenUser != null) {
                
                // 检查用户ID是否一致
                if (!threadLocalUser.getUserId().equals(tokenUser.getUserId())) {
                    log.warn("🚨 检测到用户信息不一致 - ThreadLocal用户ID: {}, Token用户ID: {}, 线程: {}, URI: {}", 
                        threadLocalUser.getUserId(), 
                        tokenUser.getUserId(),
                        Thread.currentThread().getName(),
                        request.getRequestURI());
                    
                    // 清理ThreadLocal，强制从Token获取
                    SaHolder.getStorage().delete(LOGIN_USER_KEY);
                    
                    // 记录详细信息用于问题排查
                    log.warn("已清理ThreadLocal用户信息，将从Token重新获取");
                }
                
                // 检查用户类型是否一致
                if (!threadLocalUser.getUserType().equals(tokenUser.getUserType())) {
                    log.warn("🚨 检测到用户类型不一致 - ThreadLocal: {}, Token: {}, 用户ID: {}", 
                        threadLocalUser.getUserType(), 
                        tokenUser.getUserType(),
                        tokenUser.getUserId());
                    
                    // 清理ThreadLocal
                    SaHolder.getStorage().delete(LOGIN_USER_KEY);
                }
            }
            
            // 验证LoginId的一致性
            String actualLoginId = StpUtil.getLoginIdAsString();
            if (tokenUser != null) {
                String expectedLoginId = tokenUser.getLoginId();
                if (!expectedLoginId.equals(actualLoginId)) {
                    log.error("🚨 检测到LoginId不一致 - 期望: {}, 实际: {}, 用户ID: {}", 
                        expectedLoginId, actualLoginId, tokenUser.getUserId());
                    
                    // 清理所有缓存
                    SaHolder.getStorage().delete(LOGIN_USER_KEY);
                }
            }
            
        } catch (Exception e) {
            log.error("用户一致性检查异常", e);
            // 异常时清理ThreadLocal，确保安全
            try {
                SaHolder.getStorage().delete(LOGIN_USER_KEY);
            } catch (Exception clearException) {
                log.error("清理ThreadLocal异常", clearException);
            }
        }
        
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 请求完成后的额外清理（可选）
        if (ex != null) {
            log.debug("请求异常完成，进行ThreadLocal清理");
            try {
                SaHolder.getStorage().delete(LOGIN_USER_KEY);
            } catch (Exception e) {
                log.error("请求异常后ThreadLocal清理失败", e);
            }
        }
    }
}
